<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>上传文件</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>

  <body>
    <input type="file" id="uploaderInput"/>
    <div id="videoContent" style="visibility:hidden">
      <video id="video" src="" style="width:400px" muted autoplay controls></video>
    </div>
    进度:
    <div id="process">0</div>
  </body>
</html>
<script src="./js/jquery-1.12.4.js"></script>
<script src="./js/md5.js"></script>
<script src="./js/axios.js"></script>
<script>
  /* 
  大文件上传的基本思路: 将一个大文件内容拆分多个指定大小范围内的多个小文件进行多文件请求上传
  */



  // 绑定选择文件完成后的监听
  $('#uploaderInput').on('change',function(){

    console.log('this.files', this.files)
    // 得到要上传的文件
    const file = this.files[0];
    // 上传文件
    uploadFile(file);
  })

  /* 
  上传指定的文件
  1. 对文件进行切片上传(发多个请求): file.slice(start, end)
  2. 利用formData对象来携带文件相关数据
  3. 在全部上传完成前, 根据返回的数据来显示上传进度
  4. 在全部上传完成后, 显示文件
  */
  async function uploadFile(file){

    // 得到文件内容的hash值
    const hash = await getHash(file);
    // 得到文件名中点的下标  02_用户管理_vue.mp4
    const pointIndex = file.name.lastIndexOf('.');
    // 产生新的文件名: 插入时间值  02_用户管理_vue31661957781703.mp4
    const filename = file.name.slice(0,pointIndex) + new Date().getTime() + file.name.slice(pointIndex);
    // 要拆分出的小文件的大小 2M
    const shareSize = 2*1024*1024;
    // 文件的总大小
    const size = file.size;
    // 要拆出小文件的总数量
    const total = Math.ceil(size / shareSize);

    // 要上传的小文件的下标
    let index = 0;
    // 开始对大文件进行多个小文件的上传
    upload();

    async function upload(){
      // 开始位置
      let start = index * shareSize;
      // 结束位置
      let end = (index+1)*shareSize>size ? size : (index+1)*shareSize;
      // 得到文件中对应位置的数据
      const data = file.slice(start,end);
      console.log(data)
      // 创建formData对象, 准备对当前的小文件进行上传
      const formData = new FormData();
      // 携带后台需要的数据
      formData.append('hash',hash); // 文件hash值
      formData.append('total',total); // 小文件的个数
      formData.append('index',index); // 当前要上传小文件的下标
      formData.append('data',data); // 小文件的数据
      formData.append('filename',filename); // 文件名

      // 通过axios发送提交小文件的POST请求
      const result = await axios.post('/uploadVideo', formData);
      // 下标递增, 准备上传下一个小文件
      index++;
      // 如果还不是最后一个小文件
      if(index<total){
        // 显示上传的进度
        $('#process').text(result.data.process);
        // 递归调用上传小文件的函数, 去上传下一个小文件
        upload();
      }else{
        console.log('upload success')
        // 显示上传成功的提示
        $('#process').text(result.data.msg);
        // 显示上传成功的文件(视频)
        $('#videoContent').css("visibility","visible");
        $('#video').attr("src",result.data.videoUrl)
      }
    }
  }

  /* 
  异步得到文件的hash值
  */
  function getHash(file){
    return new Promise((resolve)=>{
      // 创建FileReader对象, 将文件读取成base64值
      const reader = new FileReader();
      reader.readAsDataURL(file);
      // 在完成后, 得到文件内容的md5值, 并保存到promise中
      reader.onload=function(e){
        console.log('e.target.result', e.target.result)
        const hash = hex_md5(e.target.result);
        resolve(hash);

        // img.src = e.target.result
      }
    })
  }

  /* 
  大文件上传:
    请求上传文件: axios + FormData
    切片: file.slice(start, end)

    什么时候开始上传: file input change事件回调中
    对文件进行切片后, 遍历个切片, 对其发送上传切换相关数据的请求
  */
</script>
